import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';

import '../constants/app_constants.dart';
import '../exceptions/app_exceptions.dart';
import '../utils/logger.dart';
import 'api_response.dart';
import 'interceptors/auth_interceptor.dart';
import 'interceptors/error_interceptor.dart';
import 'interceptors/logger_interceptor.dart';

class DioClient {
  static DioClient? _instance;
  static DioClient get instance => _instance ??= DioClient._internal();
  
  late Dio _dio;
  CacheStore? _cacheStore;
  
  DioClient._internal() {
    _dio = Dio();
    _initializeDio();
  }

  Dio get dio => _dio;

  Future<void> _initializeDio() async {
    // 基础配置
    _dio.options = BaseOptions(
      baseUrl: AppConstants.baseUrl,
      connectTimeout: AppConstants.connectTimeout,
      receiveTimeout: AppConstants.receiveTimeout,
      sendTimeout: AppConstants.sendTimeout,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    );

    // 添加拦截器
    await _addInterceptors();
  }

  Future<void> _addInterceptors() async {
    // 缓存拦截器
    if (AppConstants.enableCache) {
      await _initializeCache();
      if (_cacheStore != null) {
        _dio.interceptors.add(
          DioCacheInterceptor(
            options: CacheOptions(
              store: _cacheStore!,
              policy: CachePolicy.request,
              hitCacheOnErrorExcept: [401, 403],
              maxStale: AppConstants.cacheMaxAge,
              priority: CachePriority.normal,
              cipher: null,
              keyBuilder: CacheOptions.defaultCacheKeyBuilder,
              allowPostMethod: false,
            ),
          ),
        );
      }
    }

    // 认证拦截器
    _dio.interceptors.add(AuthInterceptor());

    // 日志拦截器
    if (AppConstants.enableLogger) {
      _dio.interceptors.add(LoggerInterceptor());
    }

    // 错误拦截器
    _dio.interceptors.add(ErrorInterceptor());
  }

  Future<void> _initializeCache() async {
    try {
      if (kIsWeb) {
        // Web平台使用默认的内存缓存
        AppLogger.info('Using memory cache for web platform');
        return;
      }
      
      final appDocDir = await getApplicationDocumentsDirectory();
      _cacheStore = HiveCacheStore(
        '${appDocDir.path}/cache',
        hiveBoxName: AppConstants.cacheKey,
      );
    } catch (e) {
      AppLogger.error('Failed to initialize cache store', e);
      // 如果初始化失败，使用内存缓存
      AppLogger.info('Fallback to memory cache');
    }
  }

  // GET请求
  Future<ApiResult<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.get<Map<String, dynamic>>(
        path,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );

      return _handleResponse<T>(response, fromJson);
    } catch (e) {
      return _handleError<T>(e);
    }
  }

  // POST请求
  Future<ApiResult<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.post<Map<String, dynamic>>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );

      return _handleResponse<T>(response, fromJson);
    } catch (e) {
      return _handleError<T>(e);
    }
  }

  // PUT请求
  Future<ApiResult<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.put<Map<String, dynamic>>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );

      return _handleResponse<T>(response, fromJson);
    } catch (e) {
      return _handleError<T>(e);
    }
  }

  // DELETE请求
  Future<ApiResult<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.delete<Map<String, dynamic>>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      );

      return _handleResponse<T>(response, fromJson);
    } catch (e) {
      return _handleError<T>(e);
    }
  }

  // 文件上传
  Future<ApiResult<T>> upload<T>(
    String path,
    String filePath, {
    String? fileName,
    Map<String, dynamic>? data,
    ProgressCallback? onSendProgress,
    CancelToken? cancelToken,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final formData = FormData();
      
      if (data != null) {
        formData.fields.addAll(
          data.entries.map((e) => MapEntry(e.key, e.value.toString())),
        );
      }

      formData.files.add(
        MapEntry(
          'file',
          await MultipartFile.fromFile(
            filePath,
            filename: fileName,
          ),
        ),
      );

      final response = await _dio.post<Map<String, dynamic>>(
        path,
        data: formData,
        onSendProgress: onSendProgress,
        cancelToken: cancelToken,
      );

      return _handleResponse<T>(response, fromJson);
    } catch (e) {
      return _handleError<T>(e);
    }
  }

  // 文件下载
  Future<ApiResult<String>> download(
    String urlPath,
    String savePath, {
    ProgressCallback? onReceiveProgress,
    CancelToken? cancelToken,
    bool deleteOnError = true,
    String lengthHeader = Headers.contentLengthHeader,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      await _dio.download(
        urlPath,
        savePath,
        onReceiveProgress: onReceiveProgress,
        cancelToken: cancelToken,
        deleteOnError: deleteOnError,
        lengthHeader: lengthHeader,
        queryParameters: queryParameters,
        options: options,
      );

      return ApiResult.success(savePath);
    } catch (e) {
      return _handleError<String>(e);
    }
  }

  // 处理响应
  ApiResult<T> _handleResponse<T>(
    Response<Map<String, dynamic>> response,
    T Function(dynamic)? fromJson,
  ) {
    final data = response.data;
    if (data == null) {
      return const ApiResult.error('Response data is null');
    }

    // 假设API返回格式为 { "code": 200, "message": "success", "data": {...} }
    final code = data['code'] as int? ?? 200;
    final message = data['message'] as String? ?? 'Success';
    final responseData = data['data'];

    if (code == 200) {
      if (fromJson != null && responseData != null) {
        try {
          final result = fromJson(responseData);
          return ApiResult.success(result);
        } catch (e) {
          return ApiResult.error('Failed to parse response: $e');
        }
      } else {
        return ApiResult.success(responseData as T);
      }
    } else {
      return ApiResult.error(message, code);
    }
  }

  // 处理错误
  ApiResult<T> _handleError<T>(dynamic error) {
    final exception = ExceptionHandler.handleException(error);
    final message = ExceptionHandler.getErrorMessage(exception);
    return ApiResult.error(message, exception.code);
  }

  // 设置认证Token
  void setAuthToken(String token) {
    _dio.options.headers['Authorization'] = 'Bearer $token';
  }

  // 清除认证Token
  void clearAuthToken() {
    _dio.options.headers.remove('Authorization');
  }

  // 添加请求头
  void addHeader(String key, String value) {
    _dio.options.headers[key] = value;
  }

  // 移除请求头
  void removeHeader(String key) {
    _dio.options.headers.remove(key);
  }

  // 清除缓存
  Future<void> clearCache() async {
    try {
      await _cacheStore?.clean();
    } catch (e) {
      AppLogger.error('Failed to clear cache', e);
    }
  }

  // 关闭客户端
  void close() {
    _dio.close();
    _cacheStore?.close();
  }
}